/**
 * Browser utility
 * Cross-platform browser opening functionality
 */

const { spawn } = require('child_process');
const { getLogger } = require('../logging/logger');

const logger = getLogger();

/**
 * Browser utility class
 */
class BrowserUtil {
  /**
   * Open URL in default browser
   * @param {string} url - URL to open
   * @param {Object} options - Options
   * @returns {Promise<boolean>} Success status
   */
  static async openBrowser(url, options = {}) {
    if (!url) {
      logger.warn('No URL provided to open browser');
      return false;
    }

    try {
      const platform = process.platform;
      let command;
      let args = [];

      switch (platform) {
        case 'darwin': // macOS
          command = 'open';
          args = [url];
          break;

        case 'win32': // Windows
          command = 'cmd';
          args = ['/c', 'start', '', url];
          break;

        default: // Linux and others
          command = 'xdg-open';
          args = [url];
          break;
      }

      // Add additional options if provided
      if (options && options.incognito) {
        switch (platform) {
          case 'darwin':
            command = 'open';
            args = ['-n', '-a', 'Google Chrome', '--incognito', url];
            break;
          case 'win32':
            command = 'cmd';
            args = ['/c', 'start', 'chrome', '--incognito', url];
            break;
          default:
            // Linux incognito mode varies by browser
            args = [url]; // Fall back to normal opening
            break;
        }
      }

      // Spawn the process
      const child = spawn(command, args, {
        detached: true,
        stdio: 'ignore',
        shell: platform === 'win32'
      });

      // Don't wait for the process to complete
      child.unref();

      logger.info(`Browser opened for URL: ${url}`);
      return true;

    } catch (error) {
      logger.error(`Failed to open browser for URL: ${url}`, {
        error: error.message,
        platform: process.platform
      });
      return false;
    }
  }

  /**
   * Check if browser is available
   * @returns {Promise<boolean>} Browser availability
   */
  static async isBrowserAvailable() {
    try {
      const platform = process.platform;
      let command;

      switch (platform) {
        case 'darwin':
          command = 'open';
          break;
        case 'win32':
          command = 'start';
          break;
        default:
          command = 'xdg-open';
          break;
      }

      // Try to run the command with --help or --version to check availability
      const child = spawn(command, ['--help'], {
        detached: true,
        stdio: 'ignore'
      });

      return new Promise((resolve) => {
        child.on('error', () => resolve(false));
        child.on('spawn', () => {
          child.kill();
          resolve(true);
        });

        // Timeout after 1 second
        setTimeout(() => {
          child.kill();
          resolve(false);
        }, 1000);
      });

    } catch (error) {
      logger.debug('Browser availability check failed', error.message);
      return false;
    }
  }

  /**
   * Open browser with delay and retry
   * @param {string} url - URL to open
   * @param {Object} options - Options
   * @returns {Promise<boolean>} Success status
   */
  static async openBrowserWithRetry(url, options = {}) {
    const {
      delay = 1000,
      maxRetries = 3,
      retryDelay = 2000
    } = options;

    // Wait before opening
    if (delay > 0) {
      await new Promise(resolve => setTimeout(resolve, delay));
    }

    let lastError;
    for (let attempt = 1; attempt <= maxRetries; attempt++) {
      try {
        const success = await BrowserUtil.openBrowser(url, options);
        if (success) {
          return true;
        }
      } catch (error) {
        lastError = error;
        logger.warn(`Browser open attempt ${attempt} failed`, error.message);
      }

      // Wait before retry (except on last attempt)
      if (attempt < maxRetries) {
        await new Promise(resolve => setTimeout(resolve, retryDelay));
      }
    }

    logger.error('Failed to open browser after all retries', lastError?.message);
    return false;
  }

  /**
   * Get browser opening command for manual execution
   * @param {string} url - URL to open
   * @param {Object} options - Options for opening browser
   * @returns {Object|null} Command object with command and args, or null if no URL
   */
  static getBrowserCommand(url, options = {}) {
    if (!url) {
      return null;
    }

    const platform = process.platform;
    let command;
    let args = [];

    switch (platform) {
      case 'darwin':
        command = 'open';
        args = [url];
        break;
      case 'win32':
        command = 'cmd';
        args = ['/c', 'start', '', url];
        break;
      default:
        command = 'xdg-open';
        args = [url];
        break;
    }

    // Handle incognito mode
    if (options.incognito) {
      switch (platform) {
        case 'darwin':
          command = 'open';
          args = ['-n', '-a', 'Google Chrome', '--incognito', url];
          break;
        case 'win32':
          command = 'cmd';
          args = ['/c', 'start', 'chrome', '--incognito', url];
          break;
        default:
          // Linux incognito mode varies by browser
          args = [url]; // Fall back to normal opening
          break;
      }
    }

    return {
      command,
      args,
      platform,
      shell: platform === 'win32'
    };
  }
}

module.exports = BrowserUtil;